package com.ty.user.starter.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ty.user.starter.constants.Constant;
import com.ty.user.starter.entity.Dept;
import com.ty.user.starter.entity.User;
import com.ty.user.starter.entity.dto.DeptDto;
import com.ty.user.starter.entity.vo.DeptVo;
import com.ty.user.starter.mapper.DeptMapper;
import com.ty.user.starter.mapper.UserMapper;
import com.ty.user.starter.service.DeptService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 部门表 服务实现类
 * </p>
 *
 * @author minku
 * @since 2021-10-21
 */
@Service
public class DeptServiceImpl extends ServiceImpl<DeptMapper, Dept> implements DeptService {

    public static final String PARENT_ID = "parent_id";

    @Resource
    private UserMapper userMapper;

    /**
     * 验证部门名称是否重复
     *
     * @param id       id
     * @param parentId 父id
     * @param name     部门名称
     */
    private void validName(Long id, long parentId, String name) {
        QueryWrapper<Dept> query = new QueryWrapper<>();
        query.eq(PARENT_ID, parentId);
        query.eq("name", name);
        if (null != id) {
            query.ne("id", id);
        }
        Assert.isTrue(baseMapper.selectCount(query) == 0, "部门名称已存在");
    }

    /**
     * 验证父id以及对应的部门类型是否正确
     *
     * @param parentId 父id
     */
    private void validParentId(long parentId) {
        if (parentId != 0L) {
            this.get(parentId);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void add(DeptDto dto) {
        Assert.isNull(dto.getId(), Constant.ID_IS_NULL);
        this.validName(null, dto.getParentId(), dto.getName());
        this.validParentId(dto.getParentId());

        Dept dept = new Dept();
        BeanUtils.copyProperties(dto, dept);
        baseMapper.insert(dept);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void edit(DeptDto dto) {
        Assert.notNull(dto.getId(), Constant.ID_NOT_NULL);
        this.validName(dto.getId(), dto.getParentId(), dto.getName());
        this.validParentId(dto.getParentId());

        Dept dept = this.get(dto.getId());
        BeanUtils.copyProperties(dto, dept);
        baseMapper.updateById(dept);
    }

    /**
     * 查询部门信息
     *
     * @param id 部门id
     * @return 部门信息
     */
    private Dept get(long id) {
        Dept dept = baseMapper.selectById(id);
        Assert.notNull(dept, "部门信息不存在");
        return dept;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(long id) {
        Dept dept = baseMapper.selectById(id);
        Assert.notNull(dept, "部门信息不存在");
        // 如果只是删除当前部门,则判断是否有子部门
        QueryWrapper<Dept> query = new QueryWrapper<>();
        query.eq(PARENT_ID, id);
        this.validUser(id);
        Assert.isTrue(baseMapper.selectCount(query) == 0, "当前部门包含子部门信息,不能删除");
        baseMapper.deleteById(id);
    }

    /**
     * 验证当前部门是否与用户信息关联
     *
     * @param id 部门id
     */
    private void validUser(long id) {
        QueryWrapper<User> query = new QueryWrapper<>();
        query.eq("dept_id", id);
        Assert.isTrue(userMapper.selectCount(query) == 0, Constant.BUS_BEHAVIOR_MSG);
    }

    @Override
    public List<DeptVo> findAll() {
        List<DeptVo> list = baseMapper.findAll();
        if (list.isEmpty()) {
            return list;
        }
        return this.tree(0L, list);
    }

    private List<DeptVo> tree(Long pid, List<DeptVo> menus) {
        List<DeptVo> treeDept = new ArrayList<>();
        for (DeptVo dept : menus) {
            if (pid.equals(dept.getParentId())) {
                treeDept.add(dept);
                dept.setChildren(tree(dept.getId(), menus));
            }
        }
        return treeDept;
    }
}
